package com.universest.swordholder.task

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine

fun <T> combineTasks(name: String = "", tasks: List<AbstractTask<T,T>>): AbstractTask<T,T>{
    if(tasks.isEmpty()){
        return Task(name = name) {
            it
        }
    }
    val iterator = tasks.iterator()
    var task = iterator.next()
    while (iterator.hasNext()){
        task = task.combineTask(name = name, task = iterator.next())
    }
    return task
}

open class CombinedTask<A,B,C>(name: String = "", val taskA: AbstractTask<A,B>, val taskB: AbstractTask<B,C>):
    AbstractTask<A,C>(name), TaskGroup{

    private var _currentTask: AbstractTask<*,*>? = null
    override suspend fun call(param: A): C {
        _currentTask = taskA
        checkCancelled()
        val resultA = taskA.execute(param)
        _currentTask = null
        checkCancelled()
        val paramB = resultA.getOrThrow()
        _currentTask = taskB
        checkCancelled()
        val resultB = taskB.execute(paramB)
        _currentTask = null
        checkCancelled()
        return resultB.getOrThrow()
    }

    override val progress: Flow<Pair<Int, Int>>
        = combine(taskA.progress, taskB.progress) { a, b ->
            (a.first + b.first) to (a.second + b.second)
        }


    override val currentRunningTask: AbstractTask<*, *>
        get() {
            val task = _currentTask
            return when(task){
                null -> this
                is TaskGroup -> task.currentRunningTask
                else -> task
            }
        }

    override val tasks: List<AbstractTask<*, *>>
        get() = listOf<AbstractTask<*, *>>(taskA,taskB)

    override val message: Flow<String>
        = combine(taskA.message, taskB.message) {
            a, b ->
                if(_currentTask == taskA) a
                else if (_currentTask == taskB) b
                else ""
        }
}